'use strict';

const http = require('http');
const socketIO = require('socket.io');
const rpcRegistry = require('./registry');

/**
 * RPC服务器，用于处理RPC请求
 */
class RpcServer {
  /**
   * 构造函数
   * @param {string} serviceName 服务名称
   * @param {number} port 端口号
   * @param {string} host 主机地址
   */
  constructor(serviceName, port, host = 'localhost') {
    this.serviceName = serviceName;
    this.port = port;
    this.host = host;
    this.server = null;
    this.io = null;
  }

  /**
   * 注册服务
   * @param {string} serviceName 服务名称
   * @param {object} serviceInstance 服务实例
   * @param {boolean} isGlobal 是否为全局服务
   */
  registerService(serviceName, serviceInstance, isGlobal = false) {
    // 将服务注册到注册表
    rpcRegistry.registerLocalService(serviceName, serviceInstance, isGlobal);
    console.log(`[${this.serviceName}] 服务 ${serviceName} 已注册到 RPC 服务器`);
  }

  /**
   * 启动服务器
   * @returns {Promise<void>}
   */
  async start() {
    return new Promise((resolve, reject) => {
      try {
        // 创建HTTP服务器
        this.server = http.createServer();

        // 创建Socket.IO服务器
        this.io = socketIO(this.server);

        // 监听连接事件
        this.io.on('connection', (socket) => this._handleConnection(socket));

        // 启动HTTP服务器
        this.server.listen(this.port, this.host, () => {
          console.log(`[${this.serviceName}] RPC服务器已启动，监听: ${this.host}:${this.port}`);
          resolve();
        });
      } catch (error) {
        console.error(`[${this.serviceName}] 启动RPC服务器失败:`, error);
        reject(error);
      }
    });
  }

  /**
   * 停止服务器
   * @returns {Promise<void>}
   */
  async stop() {
    return new Promise((resolve) => {
      if (this.io) {
        this.io.close();
      }

      if (this.server) {
        this.server.close(() => {
          console.log(`[${this.serviceName}] RPC服务器已停止`);
          resolve();
        });
      } else {
        resolve();
      }
    });
  }

  /**
   * 处理Socket.IO连接
   * @param {Socket} socket Socket.IO连接对象
   * @private
   */
  _handleConnection(socket) {
    console.log(`[${this.serviceName}] 客户端已连接: ${socket.id}`);

    // 监听调用方法请求
    socket.on('invoke', async (data, callback) => {
      try {
        const { serviceName, handlerName, methodName, args } = data;
        const service = rpcRegistry.getLocalService(handlerName);

        if (!service) {
          throw new Error(`服务 ${serviceName} 不存在`);
        }
        let result;
        if (typeof (service[methodName]) !== 'function') {
          // 调用属性
          result = service[methodName];
        } else {
          // 调用服务方法
          result = await service.invoke(methodName, args);
        }

        // 返回结果，无论是否需要返回值，结果中始终包含 success 字段
        if (typeof result === 'object' && result !== null && 'success' in result) {
          // 已经是标准格式
          callback(result);
        } else {
          // 将结果包装成标准格式
          callback({ success: true, result });
        }
      } catch (error) {
        console.error(`[${this.serviceName}] 调用方法失败:`, error);
        callback({ success: false, error: error.message });
      }
    });

    // 监听断开连接事件
    socket.on('disconnect', () => {
      console.log(`[${this.serviceName}] 客户端已断开连接: ${socket.id}`);
    });
  }
}

module.exports = RpcServer; 